package com.mapbar.ure.frontend.lr1;

import com.mapbar.ure.ProductionType;

public class LR1Item {
	/*
	 * 
	 * 注意Hashset的处理方法： 1. 首先计算Hashcode。
	 * 
	 * 2. 再看是否equal。
	 * 
	 * 3. 因此，两者都要实现，如果Hashcode相同，就退化成了线性数组查找。
	 */
	public ProductionType left;
	public ProductionType[] right;
	public int placeholder;
	public ProductionType terminalSymbol;

	public LR1Item(ProductionType left, ProductionType[] right,
			int placeholder, ProductionType terminalSymbol) {
		this.left = left;
		this.right = right;
		this.placeholder = placeholder;
		this.terminalSymbol = terminalSymbol;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof LR1Item) {
			LR1Item t = (LR1Item) obj;
			if ((left == t.left || left.equals(t.left))
					&& placeholder == t.placeholder
					&& (terminalSymbol == t.terminalSymbol || terminalSymbol
							.equals(t.terminalSymbol))) {
				if (right == t.right) {
					return true;
				}
				if (right.length == t.right.length) {
					for (int i = 0; i < right.length; ++i) {
						if (right[i] != t.right[i]) {
							return false;
						}
					}
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * TODO 待实现,以提高HashSet的性能，目前相当于线性表查找
	 */
	@Override
	public int hashCode() {
		return 9;
		// return super.hashCode();
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(left);
		sb.append("\t");
		sb.append("-->");
		for (int i = 0; i < right.length; ++i) {
			if (i == placeholder) {
				sb.append(" . ");
			}
			sb.append(right[i]);
			sb.append("\t");
		}
		sb.append(",\t");
		sb.append(terminalSymbol);
		return sb.toString();
	}

	public boolean nextSymbolIsNonterminal() {
		if (placeholder < right.length) {
			return ProductionType.isNonterminal(right[placeholder]);
		} else {
			return false;
		}

	}

	public ProductionType nextSymbol() {
		if (placeholder < right.length) {
			return right[placeholder];
		}
		return null;
	}

	public boolean nextSymbolAfterPlaceholderIs(ProductionType x) {
		if (placeholder < right.length) {
			return right[placeholder] == x;
		}
		return false;
	}

	public ProductionType nextNextSymbol() {
		if (placeholder + 1 < right.length) {
			return right[placeholder + 1];
		} else {
			return null;
		}
	}

}
